package JavaEE.ManyThread7;
import java.util.*;
import java.util.concurrent.*;

public class Demo1 {
    public static void main(String[] args) throws InterruptedException{
        // 1.固定线程数目的线程池,核心线程数和最大线程数都是50
        // (优点:线程数固定,稳定) (缺点:无界队列,"任务添加速度>线程处理速度"可能OOM"内存溢出") (适用场景:任务量可控)
        ExecutorService service = Executors.newFixedThreadPool(50);
        // 2.核心线程数设置为0,最大线程数设置成一个 "int最大值" 这样的线程池.
        // (优点:弹性伸缩,适合短任务) (缺点:可能创建过多线程) (适用场景:短时高并发)
        ExecutorService service1 = Executors.newCachedThreadPool();
        // 3.固定只有一个线程的线程池,(用的不多.可以用于代替创建线程的方式)
        ExecutorService service2 = Executors.newSingleThreadExecutor();
        // 4.这个线程池,本质上是"定时器",放到这个线程池中的任务,会在一定时间之后执行.
        ExecutorService service3 = Executors.newScheduledThreadPool(10);
        // 5.手动创建线程池,完全可控.
        ExecutorService executor = new ThreadPoolExecutor(
                5,                               // 核心线程数
                10,                                         // 最大线程数
                60, TimeUnit.SECONDS,                       // 线程空闲存活时间
                new ArrayBlockingQueue<>(100),      // 有界队列（防止OOM）
                Executors.defaultThreadFactory(),           // 默认线程工厂
                new ThreadPoolExecutor.CallerRunsPolicy()   // 拒绝策略（由提交任务的线程执行）
        );
        /*
         * "lambda表达式 或 匿名内部类"
         *
         * 1.变量捕获问题:
         * "lambda表达式 或 匿名内部类"会捕获外部作用域的变量
         * 但只能捕获"final"/"等效于final"的局部变量,而i++循环改变,不符合条件
         *
         * 2.为什么要求"final"/"等效于final"?
         * 为了确保变量的值在匿名内部类内部和外部保持一致
         * 如果不符合要求,可能导致"多线程环境下的数据竞争问题"
         * (因为Runnable可能在未来的某个时间点运行,而i的值可能已经改变)
         *
         */
        for(int i = 0;i < 50;i++) {
            // 当我们想知道"这是第几个Runnable"时,无法直接通过i获得
            // 这是因为"lambda表达式 或 匿名内部类"的"变量捕获问题":
            try {
                int num = i;
                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("执行一个任务:" + num);
                    }
                };
                // submit方法:
                // 线程池中用于提交任务的核心方法.
                service.submit(runnable);
                Thread.sleep(200);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}
